/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <test_utilities/test_base.h>
#include <mc/engine.h>
#include <mc/common.h>
#include "../../../../drivers/bus/i2c_mux/i2c_mux.h"
#include "../../../../drivers/internal/manager.h"
#include "../../../../drivers/bus/i2c/i2c.h"

namespace drivers {
namespace bus {
namespace i2c_mux {
namespace test {

class i2c_mux_test_service : public mc::engine::service {
public:
    i2c_mux_test_service(const std::string& name) : mc::engine::service(name) {}
};

class I2cMuxTest : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service = mc::make_shared<i2c_mux_test_service>("bmc.kepler.test_i2c_mux");
        m_test_service->init();
        m_test_service->start();
    }

    static void TearDownTestSuite() {
        if (m_test_service) {
            m_test_service->stop();
            m_test_service.reset();
        }
        // 清理管理器
        auto& manager = dev::device_manager::get_instance();
        manager.clear_all();
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {
        // 创建I2C总线对象，供i2c_mux使用
        auto& manager = dev::device_manager::get_instance();
        mc::mutable_dict bus_csr;
        bus_csr["Id"] = static_cast<uint8_t>(1);
        m_bus = manager.create_bus("test_i2c_bus", "I2c", bus_csr);
        ASSERT_NE(m_bus, nullptr);

        // 创建i2c_mux对象
        m_i2c_mux = mc::make_shared<dev::i2c_mux_object>();
        m_i2c_mux->set_service(m_test_service.get());
        m_i2c_mux->set_object_name("test_i2c_mux");
        m_test_service->register_object(m_i2c_mux);
    }

    void TearDown() override {
        if (m_i2c_mux) {
            m_test_service->unregister_object(m_i2c_mux);
            m_i2c_mux.reset();
        }
        // 清理管理器中的bus对象
        auto& manager = dev::device_manager::get_instance();
        manager.remove_object("test_i2c_bus", dev::object_type::bus);
    }

    mc::mutable_dict create_test_csr() {
        mc::mutable_dict csr;
        csr["object_name"] = std::string("test_i2c_bus");
        csr["ChannelId"] = static_cast<uint8_t>(1);
        return csr;
    }

    mc::dict create_test_connector() {
        return mc::dict{{"SystemId", 1}};
    }

    static mc::shared_ptr<i2c_mux_test_service> m_test_service;
    std::shared_ptr<dev::bus_base> m_bus;
    mc::shared_ptr<dev::i2c_mux_object> m_i2c_mux;
};

mc::shared_ptr<i2c_mux_test_service> I2cMuxTest::m_test_service;

// ========================= 基本功能测试 =========================

TEST_F(I2cMuxTest, Constructor) {
    dev::i2c_mux_object i2c_mux;
    EXPECT_TRUE(true);
}

TEST_F(I2cMuxTest, Init_Success) {
    auto csr = create_test_csr();
    auto connector = create_test_connector();
    
    bool result = m_i2c_mux->init(csr, connector);
    EXPECT_TRUE(result);
    
    // 验证bus已设置
    EXPECT_NE(m_i2c_mux->m_interface_i2c_mux.m_bus, nullptr);
}

TEST_F(I2cMuxTest, Init_EmptyCsr) {
    mc::mutable_dict empty_csr;
    auto connector = create_test_connector();
    
    bool result = m_i2c_mux->init(empty_csr, connector);
    EXPECT_FALSE(result);
}

TEST_F(I2cMuxTest, Init_BusNotFound) {
    mc::mutable_dict csr;
    csr["object_name"] = std::string("non_existent_bus");
    csr["ChannelId"] = static_cast<uint8_t>(1);
    auto connector = create_test_connector();
    
    bool result = m_i2c_mux->init(csr, connector);
    EXPECT_FALSE(result);
}

TEST_F(I2cMuxTest, GetId_Success) {
    auto csr = create_test_csr();
    auto connector = create_test_connector();
    
    bool result = m_i2c_mux->init(csr, connector);
    ASSERT_TRUE(result);
    
    uint8_t id = m_i2c_mux->get_id();
    EXPECT_EQ(id, 1);
}

TEST_F(I2cMuxTest, GetId_NotInitialized) {
    // 未初始化时调用get_id
    uint8_t id = m_i2c_mux->get_id();
    // 应该返回默认值或0
    EXPECT_EQ(id, 0);
}

// ========================= 异常处理测试 =========================

TEST_F(I2cMuxTest, Init_InvalidBusType) {
    // 创建一个chip对象而不是bus对象
    auto& manager = dev::device_manager::get_instance();
    mc::mutable_dict chip_csr;
    chip_csr["Address"] = static_cast<uint32_t>(0x70);
    auto chip = manager.create_chip("test_chip", "Chip", chip_csr);
    ASSERT_NE(chip, nullptr);
    
    mc::mutable_dict csr;
    csr["object_name"] = std::string("test_chip");
    csr["ChannelId"] = static_cast<uint8_t>(1);
    auto connector = create_test_connector();
    
    // 应该失败，因为test_chip是chip而不是bus
    bool result = m_i2c_mux->init(csr, connector);
    EXPECT_FALSE(result);
}

TEST_F(I2cMuxTest, Init_MissingObjectName) {
    mc::mutable_dict csr;
    // 缺少object_name字段
    csr["ChannelId"] = static_cast<uint8_t>(1);
    auto connector = create_test_connector();
    
    bool result = m_i2c_mux->init(csr, connector);
    EXPECT_FALSE(result);
}

// ========================= 多实例测试 =========================

TEST_F(I2cMuxTest, MultiInstance) {
    auto& manager = dev::device_manager::get_instance();
    std::vector<mc::shared_ptr<dev::i2c_mux_object>> muxes;
    
    // 创建多个i2c_mux实例
    for (int i = 0; i < 3; ++i) {
        std::string bus_name = "test_i2c_bus_" + std::to_string(i);
        mc::mutable_dict bus_csr;
        bus_csr["Id"] = static_cast<uint8_t>(i + 1);
        auto bus = manager.create_bus(bus_name, "I2c", bus_csr);
        ASSERT_NE(bus, nullptr);
        
        auto mux = mc::make_shared<dev::i2c_mux_object>();
        mux->set_service(m_test_service.get());
        mux->set_object_name("test_i2c_mux_" + std::to_string(i));
        m_test_service->register_object(mux);
        
        mc::mutable_dict csr;
        csr["object_name"] = bus_name;
        csr["ChannelId"] = static_cast<uint8_t>(i);
        auto connector = create_test_connector();
        
        bool result = mux->init(csr, connector);
        EXPECT_TRUE(result);
        
        muxes.push_back(mux);
    }
    
    // 验证所有实例都正常工作
    for (size_t i = 0; i < muxes.size(); ++i) {
        uint8_t id = muxes[i]->get_id();
        EXPECT_EQ(id, static_cast<uint8_t>(i));
    }
    
    // 清理
    for (auto& mux : muxes) {
        m_test_service->unregister_object(mux);
    }
    for (int i = 0; i < 3; ++i) {
        std::string bus_name = "test_i2c_bus_" + std::to_string(i);
        manager.remove_object(bus_name, dev::object_type::bus);
    }
}

} // namespace test
} // namespace i2c_mux
} // namespace bus
} // namespace drivers



